package com.wuhao.code.check.model.base

import com.aegis.kotlin.toUnderlineCase
import com.aegis.mybatis.xmlless.AnnotationSupport
import com.aegis.mybatis.xmlless.annotations.Count
import com.aegis.mybatis.xmlless.annotations.JoinTableColumn
import com.aegis.mybatis.xmlless.annotations.LogicDeleteStatus
import com.aegis.mybatis.xmlless.annotations.SelectedProperties
import com.aegis.mybatis.xmlless.constant.Annotations
import com.aegis.mybatis.xmlless.enums.JoinType
import com.aegis.mybatis.xmlless.enums.XmllessFieldFill
import com.aegis.mybatis.xmlless.enums.XmllessFieldStrategy
import com.aegis.mybatis.xmlless.model.base.BaseTableFieldWrapper
import com.intellij.psi.PsiElement
import com.wuhao.code.check.getStringAnnoValue
import com.wuhao.code.check.getStringListAnnotationValue
import com.wuhao.code.check.hasAnnotation
import com.wuhao.code.check.hasAnyAnnotation

/**
 *
 * @author 吴昊
 * @date 2024/1/24 10:41
 * @since v0.0.0
 * @version 1.0
 */
abstract class BasePsiFieldWrapper(
    val el: PsiElement
) : BaseTableFieldWrapper {

  override fun getLogicDelValueInner(): String? {
    return if (el.hasAnnotation(LogicDeleteStatus::class.java)) {
      el.getStringAnnoValue(
          LogicDeleteStatus::class.java.name,
          LogicDeleteStatus::deletedValue.name
      )
    } else {
      el.getStringAnnoValue("com.baomidou.mybatisplus.annotation.TableLogic", "delval")
    }
  }

  override fun getUpdate(): String? {
    return el.getStringAnnoValue(
        Annotations.Plus.TABLE_FIELD, "update"
    )
  }

  override fun getCount(): Count? {
    if (el.hasAnnotation(Count::class.java)) {
      val anno = Count::class.java
      return Count(
          el.getStringAnnoValue(anno, Count::targetTable)!!,
          el.getStringAnnoValue(anno, Count::joinProperty) ?: "",
          el.getStringAnnoValue(anno, Count::targetColumn)!!,
          el.getStringAnnoValue(anno, Count::countColumn)!!,
          JoinType.valueOf(el.getStringAnnoValue(anno, Count::joinType) ?: "LEFT"),
      )
    }
    return null
  }

  override fun isMarkedCreatedBy(): Boolean {
    return el.hasAnnotation(Annotations.CREATED_BY)
  }

  override fun isMarkedDeletedBy(): Boolean {
    return el.hasAnnotation(Annotations.DELETED_BY)
  }

  override fun isMarkedDeletedDate(): Boolean {
    return el.hasAnnotation(Annotations.DELETED_DATE)
  }

  override fun isMarkedLastModifiedBy(): Boolean {
    return el.hasAnnotation(Annotations.LAST_MODIFIED_BY)
  }

  override fun isMarkedCreatedDate(): Boolean {
    return el.hasAnnotation(Annotations.CREATED_DATE)
  }

  override fun isMarkedLastModifiedDate(): Boolean {
    return el.hasAnnotation(Annotations.LAST_MODIFIED_DATE)
  }

  override fun getSelectedProperties(): List<String> {
    return el.getStringListAnnotationValue(
        SelectedProperties::class.java.name, "value"
    )
  }

  override fun getFieldFillStrategy(): XmllessFieldFill {
    val fill = el.getStringAnnoValue(Annotations.Plus.TABLE_FIELD, "fill")
    return when (fill) {
      "DEFAULT"       -> XmllessFieldFill.DEFAULT
      "INSERT"        -> XmllessFieldFill.INSERT
      "UPDATE"        -> XmllessFieldFill.UPDATE
      "INSERT_UPDATE" -> XmllessFieldFill.INSERT_UPDATE
      else            -> XmllessFieldFill.DEFAULT
    }
  }

  override fun getInsertStrategy(): XmllessFieldStrategy {
    val strategy = el.getStringAnnoValue(Annotations.Plus.TABLE_FIELD, "insertStrategy")
    return toXmllessFieldStrategy(strategy)
  }

  override fun getUpdateStrategy(): XmllessFieldStrategy {
    val strategy = el.getStringAnnoValue(Annotations.Plus.TABLE_FIELD, "updateStrategy")
    return toXmllessFieldStrategy(strategy)
  }

  override fun getLogicNotDelValueInner(): String? {
    return if (el.hasAnnotation(LogicDeleteStatus::class.java)) {
      el.getStringAnnoValue(LogicDeleteStatus::class.java, LogicDeleteStatus::notDeleteValue)
    } else {
      el.getStringAnnoValue("com.baomidou.mybatisplus.annotation.TableLogic", "value")
    }
  }

  override fun isLogicDelete(): Boolean {
    return el.hasAnyAnnotation(
        "com.baomidou.mybatisplus.annotation.TableLogic",
        LogicDeleteStatus::class.java.name
    )
  }

  override fun getColumn(): String {
    AnnotationSupport.CUSTOM_COLUMN_ANNOTATIONS.forEach {
      val name = el.getStringAnnoValue(it, "name")
      if (name != null) {
        return name
      }
    }
    return getFieldName().toUnderlineCase().lowercase()
  }

  override fun getJoinTableColumn(): JoinTableColumn? {
    if (el.hasAnnotation(JoinTableColumn::class.java)) {
      val annoName = JoinTableColumn::class.java.name
      return JoinTableColumn(
          table = el.getStringAnnoValue(annoName, JoinTableColumn::table.name)!!,
          columnMapTo = el.getStringAnnoValue(annoName, JoinTableColumn::columnMapTo.name)!!,
          joinOnColumn = el.getStringAnnoValue(annoName, JoinTableColumn::joinOnColumn.name) ?: "id",
          joinType = JoinType.valueOf(el.getStringAnnoValue(annoName, JoinTableColumn::joinType.name) ?: "LEFT"),
          joinOnThisProperty = el.getStringAnnoValue(annoName, JoinTableColumn::joinOnThisProperty.name)!!,
      )
    }
    return null
  }

  private fun toXmllessFieldStrategy(strategy: String?): XmllessFieldStrategy {
    return when (strategy) {
      "IGNORED"   -> XmllessFieldStrategy.NEVER
      "ALWAYS"    -> XmllessFieldStrategy.ALWAYS
      "NOT_NULL"  -> XmllessFieldStrategy.NOT_NULL
      "NOT_EMPTY" -> XmllessFieldStrategy.NOT_EMPTY
      "DEFAULT"   -> XmllessFieldStrategy.DEFAULT
      "NEVER"     -> XmllessFieldStrategy.NEVER
      else        -> XmllessFieldStrategy.DEFAULT
    }
  }

}
